package service

import (
	"StrayAnimals/internal/initConfig"
	"StrayAnimals/pkg/errorx"
	"context"
	"errors"
	"fmt"
	"github.com/go-redis/redis/v8"
	"go.uber.org/zap"
	"gopkg.in/gomail.v2"
	"time"
)

// SendCaptchaToUser 发送验证码邮件给客户
func SendCaptchaToUser(userEmail string, captchaCode string) error {
	// 邮件配置
	from := "1138848097@qq.com"    // 发件人邮箱地址
	password := "nmkfbrnfnfyvijje" // 授权码
	smtpHost := "smtp.qq.com"      // SMTP 服务器地址
	smtpPort := 587                // SMTP 端口

	// 构造邮件内容
	m := gomail.NewMessage()
	m.SetHeader("From", from, "验证码服务")                                            // 发件人名称和邮箱
	m.SetHeader("To", userEmail)                                                  // 收件人邮箱
	m.SetHeader("Subject", "您的验证码")                                               // 邮件主题
	m.SetBody("text/plain", fmt.Sprintf("您的验证码是：%s，有效期为5分钟，请妥善保管。", captchaCode)) // 邮件正文

	// 创建邮件发送器
	d := gomail.NewDialer(smtpHost, smtpPort, from, password)

	// 发送邮件
	if err := d.DialAndSend(m); err != nil {
		zap.L().Error("Failed to send email to user", zap.Error(err))
		return err
	}

	return nil
}

// SaveCaptchaToDatabase 保存验证码到 Redis 数据库
func SaveCaptchaToDatabase(email, captcha string) error {
	var redisClient = initConfig.GetRedisClient()
	var ctx = context.TODO()
	// 设置键值对，过期时间5分钟
	err := redisClient.Set(ctx, email, captcha, 5*time.Minute).Err()
	if err != nil {
		zap.L().Error("保存验证码到 Redis 数据库失败", zap.Error(err))
		return err
	}
	return nil
}

// CheckCaptcha 检查验证码是否存在且有效
func CheckCaptcha(email string) (string, error) {
	redisClient := initConfig.GetRedisClient() // 获取 Redis 客户端
	ctx := context.TODO()

	// 从 Redis 中获取验证码
	captcha, err := redisClient.Get(ctx, email).Result()
	if err != nil {
		if errors.Is(err, redis.Nil) {
			// 验证码不存在
			zap.L().Info("验证码不存在或已过期", zap.String("email", email), zap.Error(err))
			return "", errorx.ErrCaptchaNotFound
		} else {
			// 其他 Redis 错误
			zap.L().Error("无法获取验证码", zap.String("email", email), zap.Error(err))
			return "", err
		}
	}

	// 返回有效的验证码
	return captcha, nil
}

// IsCaptchaRecentlySent 检查最近1分钟内是否已发送过验证码
func IsCaptchaRecentlySent(email string) (bool, error) {
	var redisClient = initConfig.GetRedisClient()
	var ctx = context.TODO()
	// 检查该邮箱是否存在于 Redis 中
	_, err := redisClient.Get(ctx, email).Result()
	if errors.Is(err, redis.Nil) {
		// 不存在，可以发送
		return false, nil
	} else if err != nil {
		// 其他错误
		zap.L().Error("无法检查邮箱是否存在于Redis中", zap.Error(err))
		return false, err
	}

	// 如果存在，则获取其剩余 TTL
	ttl, err := redisClient.TTL(ctx, email).Result()
	if err != nil {
		zap.L().Error("无法获取剩余的TTL", zap.Error(err))
		return false, err
	}

	// 如果剩余时间小于4分钟（即已存储超过1分钟），也可以重新发送
	if ttl.Minutes() < 4 {
		return false, nil
	}

	// 否则认为在1分钟内已经发送过了
	return true, nil
}

// DeleteCaptcha 删除存储的验证码
func DeleteCaptcha(email string) {
	client := initConfig.GetRedisClient()
	ctx := context.TODO()

	// 删除 Redis 中对应的验证码 key
	_, err := client.Del(ctx, email).Result()
	if err != nil {
		zap.L().Error("删除验证码失败", zap.String("email", email), zap.Error(err))
	}

	zap.L().Info("验证码已成功删除", zap.String("email", email))
}
